package cloud.xlh.infrastructure.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.FastDateFormat;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 *
 * @ project name : xlh_osms
 * @ Author: XuLeHuang
 * @ Date: 2022/12/4 13:17
 * @ Description: 日期处理工具类 joda-time依赖
 *                参考：Home： http://joda-time.sourceforge.net/
 *                     JavaDoc： http://joda-time.sourceforge.net/apidocs/index.html
 *                     CSDN:http://t.csdn.cn/GeRZ1
 */
/**
 * todo
 * 优化：threadLocal 线程隔离
 * 拓展：jdk的localDateTime
 * */
@Slf4j
public class DateUtil {
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String HHMMSS_FORMAT = "HHmmss";
    public static final String YYYYMMDD_FORMAT = "yyyyMMdd";

    private static final ThreadLocal<SimpleDateFormat> sdfThreadLocal = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
            return sdf;
        }
    };
    private static final ThreadLocal<DateTime> dateTimeThreadLocal = new ThreadLocal<DateTime>() {
        @Override
        protected DateTime initialValue() {
            DateTime dateTime = new DateTime();
            return dateTime;
        }
    };

    /**
     * 获取当前时间
     * */
    public static DateTime getCurrentDateTime() {
        DateTime currentDateTime = dateTimeThreadLocal.get();
        return currentDateTime;
    }


    /**
     * 按指定格式 时间->字符串
     * */
    public static String formatToStr(DateTime dateTime , String formatTxt) {
        return dateTime.toString(formatTxt);
    }

    /**
     * 按指定格式 字符串->时间
     * */
    public static DateTime formatToDateTime(String dateTimeStr , String formatTxt) {
        DateTimeFormatter format = DateTimeFormat.forPattern(formatTxt);
        return DateTime.parse(dateTimeStr, format);
    }

    /**
     * 相差天数
     * */
    public static int daysOverTwoDatetime(DateTime earlyDateTime , DateTime lateDateTime) {
        int days = Days.daysBetween(earlyDateTime, lateDateTime).getDays();
        return days;
    }

    /**
     * 加
     * */
    public static final String OPERATETYPE_PLUS = "operateType_plus";

    /**
     * 减
     * */
    public static final String OPERATETYPE_MINUS = "operateType_minus";

    /**
     * 日期变化
     * 参数解释：
     * 1.原时间 2.操作类型：加/减  3.操作单位：如年、月、星期......  4.值：如1天，2天，10天......
     * */
    public static DateTime dateTimeChange(DateTime originalDateTime , String operateType , Integer unit , int value) {

        if (OPERATETYPE_PLUS.equals(operateType)) {
            switch (unit) {
                case 000 : return originalDateTime.plusYears(value);
                case 001 : return originalDateTime.plusMonths(value);
                case 010 : return originalDateTime.plusWeeks(value);
                case 011 : return originalDateTime.plusDays(value);
                case 100 : return originalDateTime.plusHours(value);
                case 101 : return originalDateTime.plusMinutes(value);
                case 110 : return originalDateTime.plusMillis(value);
                default:;break;
            }
        } else if (OPERATETYPE_MINUS.equals(operateType)) {
            switch (unit) {
                case 000:
                    return originalDateTime.minusYears(value);
                case 001:
                    return originalDateTime.minusMonths(value);
                case 010:
                    return originalDateTime.minusWeeks(value);
                case 011:
                    return originalDateTime.minusDays(value);
                case 100:
                    return originalDateTime.minusHours(value);
                case 101:
                    return originalDateTime.minusMinutes(value);
                case 110:
                    return originalDateTime.minusMillis(value);
                default:
                    ;
                    break;
            }
        } else {

        }

        log.error("操作参数错误或其他错误，操作参数->{}" , operateType);
        throw new RuntimeException("操作参数错误或其他错误---");
    }

    public static String localDateTimeToStr(LocalDateTime localDateTime) {
        String localDateTimeToStr = localDateTime.format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        return localDateTimeToStr;
    }


    /**
     * 单位：年、月、星期、日、时、分、秒
     */
    public static enum Unit {
    YEAR(000,"年"),
    MONTH(001,"月"),
    WEEK(010,"星期"),
    DAY(011,"日"),
    HOUR(100,"时"),
    MINUTE(101,"分"),
    SECOND(110,"秒")
            ;

    private static final Set<Integer> enumSet = new HashSet<>(7);

    static {
        Arrays.asList(Unit.values()).forEach(e -> enumSet.add(e.getCode()));
    }

    public static boolean hasEnum(Integer code){
        return enumSet.contains(code);
    }


    private Integer code;

    private String desc;

        Unit(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public Integer getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }

    public static String getDesc(Integer code){
        Unit[] values = values();
        if(code == null)
            return null;
        for (Unit value : values) {
            if(value.code.equals(code)){
                return value.desc;
            }
        }
        return null;
    }


}

    /**
     * joda-time依赖的DateTime -> java.util.Date
     * */
    public static Date jadaDateTimeToDate(DateTime jadaDate) {
        return jadaDate.toDate();
    }

    /**
    * java.util.Date -> joda-time依赖的DateTime
    * */
    public static DateTime dateToJadaDate(Date date) {
        return new DateTime(date);
    }

    /**
     * 时间戳 -> DateTime
     * */
    public static DateTime currentTimeMillisToDateTime(long currentTimeMillis) {
        return new DateTime(currentTimeMillis);
    }

    /**
    * DateTime -> 时间戳
    * */
    public static long getCurrentTimeMillisFromDateTime(DateTime dateTime) {
        return dateTime.getMillis();
    }

    /**
     *
     * @return java.time.LocalDate
     * @author XuLeHuang
     * @create 2023/4/11
     * @name: 获取当前日期
     * @Description:
     **/
    public static LocalDate getLocalDate() {
        return LocalDate.now();
    }

    /**
     *
     * @param localDate 指定LocalDate类型日期
     * @param pattern 模式，例如：yyyyMMdd yyyy-MM-dd
     * @return java.time.LocalDate
     * @author XuLeHuang
     * @create 2023/4/11
     * @name: 格式化LocalDate
     * @Description:
     **/
    public static LocalDate forMatLocalDate(LocalDate localDate , String pattern) {
        if (StringUtil.isEmpty(pattern)) {
            return LocalDate.parse(localDate.toString());
        } else {
            return LocalDate.parse(localDate.toString() , java.time.format.DateTimeFormatter.ofPattern(pattern));
        }
    }

    /**
     *
     * @param localDateTime
     * @param pattern
     * @return java.lang.String
     * @author XuLeHuang
     * @create 2023/10/18
     * @name: LocalDateTime->指定的字符串格式
     * @Description:
     **/
    public static String toAppointPatternLocalDateTimeStr(LocalDateTime localDateTime ,String pattern) {
        return localDateTime.format(java.time.format.DateTimeFormatter.ofPattern(pattern));
    }

    /**
     *
     * @param localDate
     * @param pattern
     * @return java.lang.String
     * @author XuLeHuang
     * @create 2023/10/18
     * @name: LocalDate->指定的字符串格式
     * @Description:
     **/
    public static String toAppointPatternLocalDateStr(LocalDate localDate ,String pattern) {
        return localDate.format(java.time.format.DateTimeFormatter.ofPattern(pattern));
    }

    public static void main(String[] args) {
       /* System.out.println(getCurrentDateTime());
        System.out.println(daysOverTwoDatetime(getCurrentDateTime(), getCurrentDateTime().plusDays(1)));
        System.out.println(formatToStr(getCurrentDateTime(), "yyyy-MM-dd HH:mm:ss"));
        System.out.println(dateTimeChange(getCurrentDateTime(), DateUtil.OPERATETYPE_MINUS , Unit.YEAR.getCode(), 1));
        System.out.println(getCurrentTimeMillisFromDateTime(getCurrentDateTime()) == System.currentTimeMillis());
        System.out.println(getCurrentTimeMillisFromDateTime(getCurrentDateTime()));
        System.out.println(System.currentTimeMillis());*/


       /* Date date = new Date();
        System.out.println(date);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
        System.out.println(sdf.format(date));*/

        LocalDate now = LocalDate.now();
        System.out.println(now.toString());
        System.out.println(LocalDate.of(1903, 6, 14));
        System.out.println(LocalDate.of(1903, Month.JUNE, 14));
        System.out.println(LocalDate.of(2023, 1, 1).plusDays(255));
        LocalDateTime localDateTime = LocalDateTime.now();

        System.out.println(localDateTime);
        System.out.println(localDateTimeToStr(localDateTime));

        System.out.println("测试：" + LocalDate.parse("2023-04-10"));
        System.out.println(LocalDate.now());
        System.out.println(LocalDate.parse("2023-04-10").isBefore(LocalDate.parse(LocalDate.now().toString())));
        System.out.println(LocalDate.now());


        String o = null;
        String o1 = null;
        try {
            o = FastDateFormat.getInstance("yyyy-MM-dd").format(new SimpleDateFormat("yyyyMMdd").parse("20230410"));
            o1 = FastDateFormat.getInstance("HH:mm:ss").format(new SimpleDateFormat("HHmmss").parse("112205"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println("o是：" + o);
        System.out.println("o1是：" + o1);

        System.out.println("1".compareTo("2"));
        System.out.println("2".compareTo("1"));
        System.out.println("2".compareTo("2"));
        LocalDate parse = LocalDate.parse(LocalDate.now().toString(), java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        System.out.println(parse.format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd")));
    }
}
